package com.imooc.pan.server.modules.file.controller;

import com.google.common.base.Splitter;
import com.imooc.pan.core.constants.RPanConstants;
import com.imooc.pan.core.response.R;
import com.imooc.pan.core.utils.IdUtil;
import com.imooc.pan.server.common.utils.UserIdUtil;
import com.imooc.pan.server.modules.file.constants.FileConstants;
import com.imooc.pan.server.modules.file.context.*;
import com.imooc.pan.server.modules.file.converter.FileConverter;
import com.imooc.pan.server.modules.file.entity.RPanUserFile;
import com.imooc.pan.server.modules.file.enums.DelFlagEnum;
import com.imooc.pan.server.modules.file.po.*;
import com.imooc.pan.server.modules.file.service.RPanUserFileService;
import com.imooc.pan.server.modules.file.vo.*;
import com.imooc.pan.server.modules.user.service.RPanUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@Slf4j
public class FileController {
    @Autowired
    private RPanUserFileService userFileService;
    @Autowired
    private FileConverter fileConverter;
    @GetMapping("/files")
    public R<List<RPanUserFileVo>> list(@NotBlank(message = "父文件夹id不能为空")
                                            @RequestParam(value = "parentId",required = false) String parentId,
    @RequestParam(value = "fileTypes",required = false,defaultValue = FileConstants.ALL_FILE_TYPE)String fileTypes){
        Long realParentId = IdUtil.decrypt(parentId);
        List<Integer> fileTypeArray = null;
        if(!Objects.equals(FileConstants.ALL_FILE_TYPE,fileTypes)){
            fileTypeArray = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileTypes).stream().map(Integer::valueOf).collect(Collectors.toList());
        }
        QueryFileListContext context = new QueryFileListContext();
        context.setParentId(realParentId);
        context.setFileTypeArray(fileTypeArray);
        context.setUserId(UserIdUtil.get());
        context.setDelFlag(DelFlagEnum.No.getCode());
        List<RPanUserFileVo> result = userFileService.getFileList(context);
        return R.data(result);
    }
    @PostMapping("/file/folder")
    public R<String> createFolder(@Validated @RequestBody CreateFolderPO createFolderPO){
        CreateFolderContext context = fileConverter.createFolderPO2CreateFolderContext(createFolderPO);
        Long fileId = userFileService.createFolder(context);
        return R.data(IdUtil.encrypt(fileId));
    }
    @PutMapping("file")
    public R updateFilename(@Validated @RequestBody UpdateFilenamePO updateFilenamePO){
        UpdateFilenameContext context = fileConverter.updateFilenamePO2UpdateFilenameContext(updateFilenamePO);
        userFileService.updateFilename(context);
        return R.success();
    }
    @DeleteMapping("file")
    public R<List<RPanUserFileVo>> deleteFile(@Validated @RequestBody DeleteFilePO deleteFilePO){
        DeleteFileContext context =  fileConverter.deleteFilePO2DeleteFileContext(deleteFilePO);
        String fileIds = deleteFilePO.getFileIds();
        List<Long> fileListIds = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileIds).stream().map(IdUtil::decrypt).collect(Collectors.toList());
        context.setFileIdList(fileListIds);
        userFileService.deleteFile(context);
        return R.success();
    }

    /**
     * 文件秒传
     * @param secUploadFilePO
     * @return
     */
    @PostMapping("file/sec-upload")
    public R secUpload(@Validated @RequestBody SecUploadFilePO secUploadFilePO) {
        SecUploadFileContext context = fileConverter.secUploadFilePO2SecUploadFileContext(secUploadFilePO);
        boolean result = userFileService.secUpload(context);
        if (result) {
            return R.success();
        }
        return R.fail("文件唯一标识不存在，请手动执行文件上传");
    }
    /**
     * 单文件上传
     */
    @PostMapping("/file/upload")
    public R upload(@Validated  FileUploadPO fileUploadPO){
        FileUploadContext context = fileConverter.fileUploadPO2FileUploadContext(fileUploadPO);
        userFileService.upload(context);
        return R.success();
    }
    /**
     * 文件分片上传
     */
    @PostMapping("/file/chunk-upload")
    public R <FileChunkUploadVo> chunkUpload(@Validated FileChunkUploadPO fileChunkUploadPO){
        FileChunkUploadContext context = fileConverter.fileChunkUploadPO2FileChunkUploadContext(fileChunkUploadPO);
        FileChunkUploadVo result = userFileService.chunkUpload(context);
        return R.data(result);
    }

    /**
     * 查询已上传的文件分片
     */
    @GetMapping("/file/chunk-upload")
    public R <UploadedChunksVO> getUploadedChunks(@Validated QueryUploadedChunksPO  queryUploadedChunksPO){
        QueryUploadedChunksContext  context = fileConverter.queryUploadedChunksPO2QueryUploadedChunksContext(queryUploadedChunksPO);
        UploadedChunksVO result = userFileService.getUploadedChunks(context);
        return R.data(result);
    }
    /**
     * 文件合并
     */
    @PostMapping("/file/merge")
    public R mergeFIle(@Validated @RequestBody FileChunkMergePO fileChunkMergePO){
        FileChunkMergeContext context = fileConverter.fileChunkMergePO2FileChunkMergeContext(fileChunkMergePO);
        userFileService.mergeFile(context);
        return R.success();
    }
    /**
     * 文件下载
     */
    @GetMapping("/file/download")
    public void download(@NotBlank(message = "文件Id不能为空")@RequestParam(value = "fileId",required = false)String fileId,
                         HttpServletResponse response){
        FileDownloadContext context = new FileDownloadContext();
        context.setFileId(IdUtil.decrypt(fileId));
        context.setResponse(response);
        context.setUserId(UserIdUtil.get());
        userFileService.download(context);
    }
    /**
     * 文件预览
     */
    @GetMapping("/file/preview")
    public void preview(@NotBlank(message = "文件Id不能为空")@RequestParam(value = "fileId",required = false)String fileId,
                        HttpServletResponse response){
        FilePreviewContext context= new FilePreviewContext();
        context.setFileId(IdUtil.decrypt(fileId));
        context.setResponse(response);
        context.setUserId(UserIdUtil.get());
        userFileService.preview(context);
    }
    /**
     * 查询文件夹树
     */
    @GetMapping("/file/folder/tree")
    public R<List<FolderTreeNodeVO>> getFolderTree(){
        QueryFolderTreeContext context = new QueryFolderTreeContext();
        context.setUserId(UserIdUtil.get());
        List<FolderTreeNodeVO> result = userFileService.getFolderTree(context);
        return R.data(result);
    }

    /**
     * 文件转移
     * @param transferFilePO
     * @return
     */
    @PostMapping("/file/transfer")
    public R transfer(@Validated @RequestBody TransferFilePO transferFilePO) {
        String fileIds = transferFilePO.getFileIds();
        String targetParentId = transferFilePO.getTargetParentId();
        List<Long> fileIdList = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileIds).stream().map(IdUtil::decrypt).collect(Collectors.toList());
        TransferFileContext context = new TransferFileContext();
        context.setFileIdList(fileIdList);
        context.setTargetParentId(IdUtil.decrypt(targetParentId));
        context.setUserId(UserIdUtil.get());
        userFileService.transfer(context);
        return R.success();
    }

    /**
     * 文件复制
     * @param copyFilePO
     * @return
     */
    @PostMapping("/file/copy")
    public R copy(@Validated @RequestBody CopyFilePO copyFilePO) {
        String fileIds = copyFilePO.getFileIds();
        String targetParentId = copyFilePO.getTargetParentId();
        List<Long> fileIdList = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileIds).stream().map(IdUtil::decrypt).collect(Collectors.toList());
        CopyFileContext context = new CopyFileContext();
        context.setFileIdList(fileIdList);
        context.setTargetParentId(IdUtil.decrypt(targetParentId));
        context.setUserId(UserIdUtil.get());
        userFileService.copy(context);
        return R.success();
    }

    /**
     * 文件搜索
     * @param fileSearchPO
     * @return
     */
    @GetMapping("file/search")
    public R<List<FileSearchResultVO>> search(@Validated FileSearchPO fileSearchPO) {
        FileSearchContext context = new FileSearchContext();
        context.setKeyword(fileSearchPO.getKeyword());
        context.setUserId(UserIdUtil.get());
        String fileTypes = fileSearchPO.getFileTypes();
        if (StringUtils.isNotBlank(fileTypes) && !Objects.equals(FileConstants.ALL_FILE_TYPE, fileTypes)) {
            List<Integer> fileTypeArray = Splitter.on(RPanConstants.COMMON_SEPARATOR).splitToList(fileTypes).stream().map(Integer::valueOf).collect(Collectors.toList());
            context.setFileTypeArray(fileTypeArray);
        }
        List<FileSearchResultVO> result = userFileService.search(context);
        return R.data(result);
    }

    /**
     * 查询面包屑列表
     * @param fileId
     * @return
     */
    @GetMapping("file/breadcrumbs")
    public R<List<BreadcrumbVO>> getBreadcrumbs(@NotBlank(message = "文件ID不能为空") @RequestParam(value = "fileId", required = false) String fileId) {
        QueryBreadcrumbsContext context = new QueryBreadcrumbsContext();
        context.setFileId(IdUtil.decrypt(fileId));
        context.setUserId(UserIdUtil.get());
        List<BreadcrumbVO> result = userFileService.getBreadcrumbs(context);
        return R.data(result);
    }
}
